#ifndef YUYIN_WAVECORE_H
#define YUYIN_WAVECORE_H
#include <string>
#include <iostream>
#include <stdio.h>
#include "vector"
#include <alsa/asoundlib.h>
/*#include "ros/ros.h"
#include "std_msgs/String.h"
*/
#define BaiDuSample 8000
#define MAX_VOICE_NUMBER 10
#define MAX_BUFFER_SIZE 2000000
#define MAX_BODY_SIZE 2000000
/*
#define INTERVAL_N     20
#define PN_DATA_LENGTH 40
#define samplesPerSec  44100
#define curTime        0.1
const int pnlengthMin = 1;
const int pnlengthMax = 801;
const int startFreqPostion = 30;
 */
#define INTERVAL_N     100
#define PN_DATA_LENGTH 20
#define samplesPerSec  44100
#define curTime        0.1
const int pnlengthMin = 1;
const int pnlengthMax = 2001;
const int startFreqPostion = 5;
namespace mmjd
{
    namespace yuyin
    {
        typedef struct Condition
        {
            unsigned char messege_status = 0;
        };

        typedef struct LetterNumberFrq
        {
            unsigned char    length;
            unsigned char    letternumber[256] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127};
            unsigned int      frequency[256] = {200,220,240,260,280,300,320,340,360,380,400,420,440,460,480,500,520,540,560,580,600,620,640,660,680,700,720,740,760,780,800,820,840,860,880,900,920,940,960,980,1000,1020,1040,1060,1080,1100,1120,1140,1160,1180,1200,1220,1240,1260,1280,1300,1320,1340,1360,1380,1400,1420,1440,1460,1480,1500,1520,1540,1560,1580,1600,1620,1640,1660,1680,1700,1720,1740,1760,1780,1800,1820,1840,1860,1880,1900,1920,1940,1960,1980,2000,2020,2040,2060,2080,2100,2120,2140,2160,2180,2200,2220,2240,2260,2280,2300,2320,2340,2360,2380,2400,2420,2440,2460,2480,2500,2520,2540,2560,2580,2600,2620,2640,2660,2680,2700,2720,2740};
        }LetterNumberFrq_t;

        typedef struct WavePcmHeader
        {
            char            riff[4];
            int		    size_8;
            char            wave[4];
            char            fmt[4];
            int		    fmt_size;
            short int       format_tag;
            short int       channels;
            int		    samples_per_sec;
            int		    avg_bytes_per_sec;
            short int       block_align;
            short int       bits_per_sample;
            char            data[4];
            int		    data_size;
        }WaveObj_pcm_hdr;

        typedef short WaveDataType;

        typedef struct WaveObj
        {
            std::vector<short> data;
            unsigned int    length;
            unsigned int    simple_rate;
            float           cur_time;
            unsigned long   frequency;
        }WaveObj_t;

        typedef struct FreqObj
        {
            float           freq_step;
            unsigned int    length;
            std::vector<float> freq_volume;
            std::vector<float> frequency;
            std::vector<float> realPart;
            std::vector<float> imaginaryPart;

        }FreqObj_t;

        typedef struct ThreadShare
        {
            const int number = 256;
            bool      startflag = false;
            int       endposition = 0;
            int       length=0;
            int       gsample = samplesPerSec;
            int       startposition = 0;
            float     gsampletime = curTime;
            int       grc = gsample * gsampletime; //44100*0.025
            bool      receiveflag = false;
            float     gstartfreq = 800; //密码开始频率
            int       gfreqstep = 20; // 间隔
            int       gstartnumber = 5; //计数大于5表示密码开始输入
            int       offset = 6;
            int       passwordminlength = 5*6+5*6; //ssid ,secret
            int       passwordmaxlength = 120;

            pthread_t thread[2];
            pthread_mutex_t mut;
            WaveObj wave[256];
            WaveObj realtimewave;
            WaveObj_pcm_hdr wave_pcm_hdr;
            LetterNumberFrq_t letternumberfreq;
        }ThreadShare_t;

        class WaveCore
        {
        public:

            pthread_t pid;
            ThreadShare ThreadShare1;
            static void * start_thread1(void *arg);
            static void * start_thread2(void *arg);
            int start(void *ptr);
            //virtual void run();                                                                                         //基类中的虚函数要么实现，要么是纯虚函数（绝对不允许声明不实现，也不纯虚）
            void thread_create(void);
            void thread_wait(void);

            bool closeAudio(snd_pcm_t * &handle);
            static bool getReferenceValue(int pnlengthMin,int pnlengthMax,int maxVolumePosition,std::vector<std::vector<float> > &reference_value,std::vector<float> &referencedata);
            static bool referenceValue(int pnlengthMin,int pnlengthMax,int maxVolumePosition,int offset,const FreqObj_t &freq,std::vector<float> &reference_value);
            static bool getFreqObj1(int pnlengthMin,int pnlengthMax,int maxVolumePosition,int offset, const WaveObj_t &wave, FreqObj_t &freq);
            bool getPasswordHeadWave(const WaveObj_t &wave, unsigned int length,char &buffer);
            bool savePassword(const WaveObj_t &wave,int inputsample,int outsample);
            bool savePasswordString(const char * file_name,unsigned char &letternumber);
            float getVoiceFreq(FreqObj_t &freq);
            bool checkPasswordStart(int pnlengthMin,int pnlengthMax, const FreqObj_t &freq,int maxVolumePosition,int offset,int &currentfreq,float &currentvolume);
            bool savePassword(const char * fileName,unsigned char &letternumber);
            bool genFreqXuLie(unsigned int startfreq,int step,int length,LetterNumberFrq &LetterNumberFrq_t);
            bool getPassword1(ThreadShare * &threadsharewave,FreqObj_t &freq,unsigned int threshold);
            bool getPassword(ThreadShare * &threadsharewave,FreqObj_t &freq,int threshold);
            bool changeSample(const WaveObj_t &inputwave,WaveObj_t &outputwave,int inputsample,int outputsample);
            long gettimeMS(struct timeval time_struct);
            float getVoiceTimeAndFreq(FreqObj_t &freq,float &lastFreq);
            static WaveObj_pcm_hdr genPcm_hdr(int freq = 16000);
            bool deleteFile(const char * fileName);
            static bool readWaveFile(const char * fileName,WaveObj_t &outputwave);

            bool genPasswordWave(const char * file_name,const WaveObj_t &start_end_wave,FreqObj_t &freq,std::vector<float> pndata,
                                           const int head_times,const int password_times,const unsigned char password_data_length);
            static bool saveTimesToFile(const char * fileName,const WaveObj_t &wave,const int times);
            static bool saveCharDataToFile(const char * fileName,std::vector<short> data,int sample);
            static bool saveToFile(const char * fileName,const WaveObj_t &wave);
            static bool saveWaveDataToFile(const char * fileName,std::vector<short> wave,int sample);
            static bool dumpToFile(const char * fileName,const WaveObj_t &wave,const WaveObj_pcm_hdr &wave_pcm_hdr);
            static bool genWaveObj(const int simple_rate, const float time_duration, const int frequency, WaveObj_t &wave,const WaveObj_pcm_hdr &wave_pcm_hdr);

            static WaveObj_t genNullWaveObj(int length, unsigned long cur_time = -1,int sample_rate = 16000); static bool freeWave(WaveObj_t &wave);
            static bool freeFreq(FreqObj_t &freq);
            static bool changeSampleToBaiDuSample(std::vector<short > &inputdata, int intputlength, std::vector<short > &outputdata,int inputsample,int outputsample);
            static bool changeSampleToBaiDuSample2(std::vector<short > &inputdata, int inputlength, std::vector<short > &outputdata,int inputsample,int outputsample);
            static bool getFreqObj(const WaveObj_t &wave, FreqObj_t &freq);
            static bool gedtWav(WaveObj_t &wave, const FreqObj_t &freq);
            static void showWave( const std::string &win_name, const WaveObj_t &wave, const int wait_time ,
                                  const int begin_ = -1, const int end_ = -1,int max_sample_count =2000);
            static void showWave1( const std::string &win_name, const WaveObj_t &wave, const int wait_time ,
                                   const int begin_ = -1, const int end_ = -1,int max_sample_count =2000);
            static void showFreq( const std::string &win_name, const FreqObj_t &freq, const float max_volume = 200000,
                                  const int max_sample_num = 300, int min_freq = -1, int max_freq = 22*1000,const int wait_time = 10);
            bool isVoise(std::vector<short> &in, int length);
            void processVoice(std::vector<short> &a,int length, double *out_r);
            void showData(double *data,int length,int width,int height,int beam, double m_max);
            bool initAudioDev(snd_pcm_t * &handle,snd_pcm_stream_t stream,unsigned int sample,float sampletime);
            bool listenAudio(WaveObj_t &wave,snd_pcm_t * &handle,unsigned sample,float sampletime,bool onoff);
            static bool getWaveFromFreq(WaveObj_t &wave, const FreqObj_t &freq);
        };

    }

}

#endif
